package com.factory.iamp.controller.advice;

import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.factory.iamp.utils.exception.APIException;
import com.factory.iamp.utils.helper.ResponseCode;
import com.factory.iamp.utils.helper.ResponseHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.support.MissingServletRequestPartException;

import javax.validation.ConstraintViolationException;
import java.sql.SQLIntegrityConstraintViolationException;

@RestControllerAdvice(basePackages = {"com.factory.iamp.controller"})
public class ExceptionAdvice {
    private static final Logger logger = LoggerFactory.getLogger(ExceptionAdvice.class);

    @ExceptionHandler(APIException.class)
    public ResponseHelper<String> APIExceptionHandler(APIException e) {
        logger.error(e.getMsg());
        return new ResponseHelper<>(e.getCode(), e.getMsg());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseHelper<String> MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
        ObjectError objectError = e.getBindingResult().getAllErrors().get(0);
        logger.error(objectError.getDefaultMessage());
        return new ResponseHelper<>(ResponseCode.VALIDATE_FAILED, objectError.getDefaultMessage());
    }

    @ExceptionHandler(ConstraintViolationException.class)
    public ResponseHelper<String> ConstraintViolationExceptionHandler(ConstraintViolationException e) {
        logger.error(e.getMessage());
        return new ResponseHelper<>(ResponseCode.VALIDATE_FAILED, e.getMessage());
    }

    @ExceptionHandler(JWTDecodeException.class)
    public ResponseHelper<String> JWTDecodeExceptionHandler(JWTDecodeException e) {
        return new ResponseHelper<>(ResponseCode.VALIDATE_FAILED, "token错误，请重新登录");
    }

    @ExceptionHandler(SignatureVerificationException.class)
    public ResponseHelper<String> SignatureVerificationExceptionHandler(SignatureVerificationException e) {
        return new ResponseHelper<>(ResponseCode.VALIDATE_FAILED, "token错误，请重新登录");
    }

    @ExceptionHandler(MissingServletRequestPartException.class)
    public ResponseHelper<String> MissingServletRequestPartExceptionHandler(MissingServletRequestPartException e) {
        logger.error(e.getMessage());
        return new ResponseHelper<>(ResponseCode.VALIDATE_FAILED, e.getMessage());
    }

    @ExceptionHandler(MissingServletRequestParameterException.class)
    public ResponseHelper<String> MissingServletRequestParameterExceptionHandler(MissingServletRequestParameterException e) {
        logger.error(e.getMessage());
        return new ResponseHelper<>(ResponseCode.VALIDATE_FAILED, e.getMessage());
    }

    @ExceptionHandler(SQLIntegrityConstraintViolationException.class)
    public ResponseHelper<String> SQLIntegrityConstraintViolationExceptionHandler(SQLIntegrityConstraintViolationException e) {
        logger.error(e.getMessage());
        return new ResponseHelper<>(ResponseCode.DATABASE_FAILED, e.getMessage());
    }

    @ExceptionHandler(Throwable.class)
    public ResponseHelper<String> AnyExceptionHandler(Throwable e) {
        logger.error(e.getClass().getName());
        int cnt = 0;
        for(StackTraceElement x: e.getStackTrace()) {
            cnt += 1;
            logger.error(x.toString());
            if(cnt >= 10) break;
        }
        e.printStackTrace();
        return new ResponseHelper<>(ResponseCode.ERROR, e.getClass().getName());
    }
}
